package org.firefly.config;

import org.firefly.component.QuartzHealthIndicator;
import org.firefly.component.QuartzJobRecovery;
import org.firefly.repository.TimeCapsuleRepository;
import org.firefly.service.TimeCapsuleService;
import org.quartz.Scheduler;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;

@Configuration
public class AppConfig {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired(required = false)
    private DataSource dataSource;

    @Value("${spring.mail.host}")
    private String mailHost;

    @Value("${spring.mail.port}")
    private int mailPort;

    @Value("${spring.mail.username}")
    private String mailUsername;

    @Value("${spring.mail.password}")
    private String mailPassword;

    // 自定义JobFactory以支持Spring依赖注入
    @Bean
    public SpringBeanJobFactory springBeanJobFactory() {
        AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    // Quartz属性配置
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    // Scheduler工厂Bean配置
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();

        // 设置自定义JobFactory
        factory.setJobFactory(springBeanJobFactory());

        // 配置Quartz属性
        factory.setQuartzProperties(quartzProperties());

        // 如果配置了数据源，使用JDBC存储任务
        if (dataSource != null) {
            factory.setDataSource(dataSource);
            factory.setOverwriteExistingJobs(true);
        }

        // 自动启动Scheduler
        factory.setAutoStartup(true);

        // 设置应用程序上下文Key，用于在Job中访问Spring Context
        factory.setApplicationContextSchedulerContextKey("applicationContext");

        return factory;
    }

    // 邮件发送器配置
    @Bean
    public JavaMailSender javaMailSender() {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(mailHost);
        mailSender.setPort(mailPort);
        mailSender.setUsername(mailUsername);
        mailSender.setPassword(mailPassword);

        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.debug", "true");

        return mailSender;
    }
    @Bean
    public QuartzJobRecovery quartzJobRecovery(TimeCapsuleRepository capsuleRepository,
                                               TimeCapsuleService capsuleService,
                                               Scheduler scheduler) {
        return new QuartzJobRecovery(capsuleRepository, capsuleService, scheduler);
    }

    @Bean
    public QuartzHealthIndicator quartzHealthIndicator(Scheduler scheduler) {
        return new QuartzHealthIndicator(scheduler);
    }

    // 自定义JobFactory实现
    public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory {
        private AutowireCapableBeanFactory beanFactory;

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) {
            this.beanFactory = applicationContext.getAutowireCapableBeanFactory();
        }

        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            Object job = super.createJobInstance(bundle);
            beanFactory.autowireBean(job);
            return job;
        }
    }
}